<template>
  <div id="mapContainer">
    <!-- 地图控件：右下-->
    <div class="mapCtrl_right" v-show="showMapCtrl">
      <!-- 重置定位按钮-->
      <div class="mapBtn" id="home" title="重置定位" />
      <!-- 缩放地图-->
      <el-icon class="mapBtn" @click="zoomCrtl('zoomPlus')" title="放大">
        <Plus style="width: 1.5em;height:1.5em;" />
      </el-icon>
      <el-icon class="mapBtn" @click="zoomCrtl('zoomMinus')" title="缩小">
        <Minus style="width: 1.5em;height:1.5em;" />
      </el-icon>
      <!-- 地图全屏-->
      <!-- <div class="mapBtn" id="fullScreen" title="地图全屏" /> -->
    </div>
    <!-- 地图控件：中-->
    <div>
      <!-- <div id="drawTools" /> -->
      <ploting-tool
        ref="drawDom"
        @draw-click="drawClick"
        @save-graphic="saveGraphic"
        style="position:absolute; margin-right: 12px;right: 0.1rem;top: 2.6rem;"
        :lcmap="_map"
        v-if="showMapCtrl"
      />
    </div>
    <!-- 地图控件：左-->
    <div class="mapCtrl_left" v-show="showMapCtrl">
      <!--比例尺-->
      <div id="scaleBar" title="比例尺" />
      <!--坐标显示-->
      <div class="mapPosition">
        <p> {{ mapPosition.x }},{{ mapPosition.y }}</p>
      </div>
    </div>
    <!-- 应用控件：图层面板-->
    <div>
      <!-- <Dialog-Gis style="position:absolute;left:10px;top:10px" />
      <dialog-search style="position:absolute;right:10px;top:30%" />
      <dialog-user-data style="position:absolute;left:30%;top:3%" />
      <dialog-video style="position:absolute;left:30%;top:50%" /> -->
    </div>
  </div>
</template>
<script lang="ts" setup>
import { onMounted, ref, reactive, toRaw, computed, watch } from 'vue'
import { getToken } from '@/utils/auth'
import { Config } from '@/store'
import { Plus, Minus } from '@element-plus/icons'
import { ElMessage } from 'element-plus'
import { createDraw, deleteDraw } from '@/api/mapData'
// import * as turf from '@turf/turf'
// import { getMapConfig } from '@/api/mapServices'
// 地图参数配置
const config = getToken('unify-config') as Config
// 接收父组件的传值
const props = defineProps({
  layerListData: {
    type: Array,
    default: () => []
  }
})
const layerListData:any = computed(() => props.layerListData)
let drawButtonStatus:any = false
watch(layerListData, () => {
  if (drawButtonStatus) {
    closeDrawDialog()
    drawClick(false)
  }
})
// 传值给父组件，调用父组件方法
const emit = defineEmits(['mapDarwClick', 'mapHomeCtrl', 'getResultList', 'saveGraphic', 'openFilter', 'openInfoWindow', 'closeUserDialog', 'closeDialog'])
const drawDom = ref() // 标绘组件dom
// 点击标绘开关触发
const drawClick = (status:any) => {
  drawButtonStatus = status
  emit('mapDarwClick')
  emit('closeUserDialog')
  initDrawLayerEvent(status)
  if (status) {
    // 标绘工具打开时，其他图层监听状态
    map.mapView.map.layers.items.forEach((lyr:any) => {
      if (lyr.id && lyr.id !== 'sketchLayer') {
        lyr.popupEnabled = false
        lyr.removeLayerEvt()
        lyr.layerEvt = null
        lyr.removeLayerEvt = null
      }
    })
    // layerListData.value.forEach((item:any) => {
    //   const visible = ('visible' in item) ? item.visible : (!!Number(item.is_show) || false)
    //   if (visible) {
    //     const layer = map.getLayer(item.element_type)
    //     let hasLayer = false
    //     if (layer) {
    //       hasLayer = true
    //     }
    //     if (!hasLayer) {
    //       return
    //     }
    //     layer.removeLayerEvt()
    //     layer.layerEvt = null
    //     layer.removeLayerEvt = null
    //     console.log(item.element_type + '移除鼠标事件')
    //   }
    // })
  } else {
    emit('closeDialog')
    map.mapView.map.layers.items.forEach((lyr:any) => {
      if (lyr.id && lyr.id !== 'sketchLayer') {
        // lyr.popupEnabled = true
        lyr.initLayerEvt()
      }
    })
    // layerListData.value.forEach((item:any) => {
    //   const visible = ('visible' in item) ? item.visible : (!!Number(item.is_show) || false)
    //   if (visible) {
    //     const layer = map.getLayer(item.element_type)
    //     let hasLayer = false
    //     if (layer) {
    //       hasLayer = true
    //     }
    //     if (!hasLayer) {
    //       return
    //     }
    //     layer.initLayerEvt()
    //   }
    // })
  }
}
let selectedGraphic:any = null // 点击选中的标绘框
let hoverGraphic:any = null // 鼠标悬浮的标绘框
let clickEvt:any = null // 鼠标悬浮的标绘框
let rightclickEvt:any = null // 鼠标悬浮的标绘框
let hoverEvt:any = null // 鼠标悬浮的标绘框
const initDrawLayerEvent = (status:any) => {
  const sketchLayer = map.getLayer('sketchLayer')
  map.mapView.map.reorder(sketchLayer, 999)
  if (status) {
    // 标绘工具打开时，标绘图层监听状态。
    const symbol = {
      type: 'simple-fill',
      color: [128, 128, 128, 0], // 填充颜色
      outline: { // 边线颜色及线条宽度
        style: 'dot',
        color: '#2eade8',
        width: 1.5
      }
    }
    const selSymbol = {
      type: 'simple-fill',
      color: [126, 128, 35, 0.12], // 填充颜色
      outline: { // 边线颜色及线条宽度
        color: '#2eade8',
        width: 1.5
      }
    }
    const hoverSymbol = {
      type: 'simple-fill',
      color: [126, 128, 35, 0.12], // 填充颜色
      outline: { // 边线颜色及线条宽度
        style: 'dot',
        color: '#2eade8',
        width: 1.5
      }
    }
    clickEvt = map.layerClickHandler('sketchLayer', function (evt:any) {
      if (selectedGraphic) {
        selectedGraphic.symbol = symbol
      }
      if (evt && evt.length > 0 && evt[1] && evt[1].symbol) {
        evt[1].symbol = selSymbol
        selectedGraphic = evt[1]
      }
    })
    rightclickEvt = map.layerRightClickHandler('sketchLayer', function (evt:any) {
      if (selectedGraphic) {
        selectedGraphic.symbol = symbol
      }
      if (evt && evt.length > 0 && evt[1] && evt[1].symbol) {
        evt[1].symbol = selSymbol
        selectedGraphic = evt[1]
      }
      emit('openFilter', evt)
    })
    // 鼠标悬浮
    hoverEvt = map.layerHoverHandler('sketchLayer', (evt:any) => {
      if (evt && evt.length > 0 && evt[1] && evt[1].symbol) {
        if (hoverGraphic && selectedGraphic && hoverGraphic.attributes && selectedGraphic.attributes && hoverGraphic.attributes.id && selectedGraphic.attributes.id) {
          if (hoverGraphic.attributes.id === selectedGraphic.attributes.id) {
            return
          }
        }
        if (hoverGraphic && hoverGraphic.symbol) {
          hoverGraphic.symbol = symbol
        }
        hoverGraphic = evt[1]

        evt[1].symbol = hoverSymbol
      } else {
        if (hoverGraphic) {
          if (hoverGraphic && selectedGraphic && hoverGraphic.attributes && selectedGraphic.attributes && hoverGraphic.attributes.id && selectedGraphic.attributes.id) {
            if (hoverGraphic.attributes.id === selectedGraphic.attributes.id) {
              return
            }
          }
          hoverGraphic.symbol = symbol
        }
      }
    })
  } else {
    map.mapView.map.reorder(sketchLayer, 0)
    if (rightclickEvt || hoverEvt || clickEvt) {
      clickEvt.remove()
      clickEvt = null
      rightclickEvt.remove()
      rightclickEvt = null
      hoverEvt.remove()
      hoverEvt = null
    }
  }
}
// 关闭标绘弹窗
const closeDrawDialog = () => {
  if (drawDom.value) {
    drawDom.value?.closeDrawDialogone()
    closeHighlight()
  }
}
const mapParams = {
  sources: {
    arcgisUrl: config.mapConfig.sources.arcgisUrl
  },
  map: {
    center: [117.222315, 31.825451],
    zoom: 9,
    basemap: null
    // basemap: 'https://map.geoq.cn/arcgis/rest/services/ChinaOnlineStreetPurplishBlu/MapServer'
    // basemap: 'https://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineStreetGray/MapServer'
    // basemap: 'https://iserver.supermap.io/iserver/services/map-china400/wmts100'
  },
  basemaps: {
    image: {
      type: 'wmts',
      id: 'image',
      url: config.mapConfig.basemaps.image.url || null,
      layerID: config.mapConfig.basemaps.image.layerID || null,
      tileMatrixSetId: config.mapConfig.basemaps.image.tileMatrixSetId || null
    },
    image_label: {
      type: 'wmts',
      id: 'image_label',
      url: config.mapConfig.basemaps.image_label.url || null,
      layerID: config.mapConfig.basemaps.image_label.layerID || null,
      tileMatrixSetId: config.mapConfig.basemaps.image_label.tileMatrixSetId || null
    },
    vector: {
      type: 'wmts',
      id: 'vector',
      url: config.mapConfig.basemaps.vector.url || null,
      layerID: config.mapConfig.basemaps.vector.layerID || null,
      tileMatrixSetId: config.mapConfig.basemaps.vector.tileMatrixSetId || null
    },
    vector_D: {
      type: 'wmts',
      id: 'vector_D',
      url: config.mapConfig.basemaps.vector_D.url || null,
      layerID: config.mapConfig.basemaps.vector_D.layerID || null,
      tileMatrixSetId: config.mapConfig.basemaps.vector_D.tileMatrixSetId || null
    }
  },
  layers: {}
}
// "arcgisUrl": "http://220.171.131.170:18080/mapsdk/res2d/",
// 全局变量
const showMapCtrl = ref(false)
let LcMap:any = null
let map:any = null
const _map:any = ref(null)

// 获取arcgis依赖地址
const arcgigUrl:string = config.arcgisUrl
onMounted(() => {
  // 若已存在js文件，则先清除，再重新加载.
  const scriptList = document.getElementsByTagName('script')
  Array.prototype.forEach.call(scriptList, function (item) {
    if (item.src.indexOf(`${arcgigUrl}map2d.js`) > -1) {
      item.remove()
    }
  })
  // 加载依赖资源map2d.js
  const mapJS:any = document.createElement('script')
  mapJS.src = `${arcgigUrl}map2d.js`
  document.body.append(mapJS)
  mapJS.onload = function () {
    LcMap = window.LcMap
    initMap()
  }
})
// 初始化地图
const initMap = () => {
  _map.value = new LcMap()
  map = toRaw(_map.value)
  const options = {
    arcgisUrl: mapParams.sources.arcgisUrl, // api地址(必需参数)
    center: mapParams.map.center,
    maxZoom: 12,
    zoom: mapParams.map.zoom,
    baseMap: mapParams.map.basemap // 地图地址(必需参数)
  }
  // 初始化底图
  map.initMap('mapContainer', options).then((res: any) => {
    const layerConfig = mapParams.basemaps.vector_D
    // 加载webTileLayer底图
    // const wlayer = new map.ArcGisMapObj.WebTileLayer({
    //   // id: layerConfig.id,
    //   urlTemplate: layerConfig.url + `?SERVICE=WMTS&VERSION=1.0.0&REQUEST=GetTile&LAYER=${layerConfig.layerID}&STYLE=default&TILEMATRIXSET=${layerConfig.tileMatrixSetId}&TILEMATRIX={level}&TILEROW={row}&TILECOL={col}&FORMAT=png` // xml文件地址'
    // })

    // 加载wmts底图
    const wlayer = new map.ArcGisMapObj.WMTSLayer({
      // id: layerConfig.id,
      url: layerConfig.url, // xml文件地址
      activeLayer: {
        id: layerConfig.layerID || null, // xml文件中的图层id
        tileMatrixSetId: layerConfig.tileMatrixSetId || null
      }
    })
    // 创建一个新的底图
    const baseMapNew = new map.ArcGisMapObj.Basemap({
      baseLayers: [wlayer]
    })
    // 创建map
    const gismap = new map.ArcGisMapObj.GisMap({
      basemap: baseMapNew
    })
    const mapView = new map.ArcGisMapObj.MapView({
      container: res.divId,
      constraints: {
        rotationEnabled: false // 禁止旋转
      },
      map: gismap,
      ui: res.ui,
      center: res.center
    })
    map.mapView = mapView
    mapView.when(() => {
      // console.log(mapView.map.basemap.baseLayers.items[0].tilemapCache.tileInfo.scales[9])
      mapView.scale = mapView.map.basemap.baseLayers.items[0].tilemapCache.tileInfo.scales[res.zoom]
      // 加载前端面板
      emit('mapHomeCtrl')
      initMapCtrl()
      initMapEvt()
    })
    // window.lcmap = map
    // 叠加地图
    // toggleBasemap('fg_as')
    // getMapConfig().then((res:any) => {
    //   console.log(res)
    // })
    // 默认开启地图控件
    // initMapCtrl()
    // initDrawToos()
    // addFeatureLayer()
    // 初始化地图监听事件
    // initMapEvt()
  })
}
// 切换底图
const toggleBasemap = (type:any) => {
  const addWMTS = (layerConfig:any) => {
    if (layerConfig.url === '' || !layerConfig.url) {
      ElMessage({
        type: 'warning',
        message: '暂无此类型地图数据!',
        duration: 2000,
        showClose: true
      })
      return
    }
    // 加载wmts底图
    const wlayer = new map.ArcGisMapObj.WMTSLayer({
      // id: layerConfig.id,
      url: layerConfig.url, // xml文件地址
      activeLayer: {
        id: layerConfig.layerID || null, // xml文件中的图层id
        tileMatrixSetId: layerConfig.tileMatrixSetId || null
      }
    })
    // 创建一个新的底图
    const baseMapNew = new map.ArcGisMapObj.Basemap({
      baseLayers: [wlayer]
    })
    map.mapView.map.basemap = baseMapNew // 切换底图
  }
  switch (type) {
    case 'dtxz_wxt' : {
      const layerConfig = mapParams.basemaps.image
      addWMTS(layerConfig)
      break
    }
    case 'dtxz_lwt': {
      const layerConfig = mapParams.basemaps.image_label
      addWMTS(layerConfig)
      break
    }
    case 'fg_ls': {
      const layerConfig = mapParams.basemaps.vector
      addWMTS(layerConfig)
      break
    }
    case 'fg_as': {
      const layerConfig = mapParams.basemaps.vector_D
      addWMTS(layerConfig)
      break
    }
  }
}
// 地图控件——初始化
const mapPosition = reactive({ // 用于显示鼠标所在位置坐标
  x: mapParams.map.center[0],
  y: mapParams.map.center[1]
})
const initMapCtrl = () => {
  // 显示地图控件
  showMapCtrl.value = true
  // 默认视图
  const homeBtn = new map.ArcGisMapObj.Home({
    view: map.mapView,
    container: 'home'
  })
  // 默认最大层级
  map.mapView.constraints.minZoom = 5
  // 显示比例尺
  const scaleBar = new map.ArcGisMapObj.ScaleBar({
    view: map.mapView,
    container: 'scaleBar',
    unit: 'metric'
  })
  // 地图全屏
  const fullScreen = new map.ArcGisMapObj.Fullscreen({
    view: map.mapView,
    container: 'fullScreen'
  })

  // 地图控件——鼠标拾取坐标
  map.mapView.on('pointer-move', (event:any) => {
    const point = map.mapView.toMap({ x: event.x, y: event.y })
    mapPosition.x = point.longitude.toFixed(6)
    mapPosition.y = point.latitude.toFixed(6)
  })
}
// 地图控件——地图缩放方法
const zoomCrtl = (type:any) => {
  const zoom = new map.ArcGisMapObj.Zoom({
    viewModel: {
      view: map.mapView
    }
  })
  switch (type) {
    case 'zoomPlus': {
      zoom.zoomIn()
      break
    }
    case 'zoomMinus': {
      zoom.zoomOut()
      break
    }
  }
}
// 地图鼠标事件
const initMapEvt = () => {
  map.mapView.on(['click'], function (event:any) {
    map.mapView.hitTest(event).then(function (response:any) {
      if (response.results.length === 0) {
        emit('closeDialog')
      }
    })
  })
}
// 地图缩放至图层
const goToFeatureLayer = (layerId:any) => {
  const layer = map.getLayer(layerId)
  let hasLayer = false
  if (layer) {
    hasLayer = true
  }
  if (!hasLayer) {
    return
  }
  const graphicArr = layer.source.items
  map.mapView.goTo(graphicArr)
}
// 当前高亮要素
let highligh:any = null
// 取消当前高亮
const closeHighlight = () => {
  if (highligh) {
    highligh.remove()
    highligh = null
  }
}
// 定位到要素
const goToFeature = (_feature:any) => {
  const feature = toRaw(_feature)
  map.mapView.whenLayerView(feature.layer).then((layerView:any) => {
    closeHighlight()
    highligh = layerView.highlight(feature)
  })
  map.mapView.goTo({ target: feature.geometry, zoom: 18 }, { duration: 1500 }).then((res:any) => {
    // console.log(feature)
    // 打开弹窗
    const screePoints = map.mapView.toScreen(feature.geometry)
    emit('openInfoWindow', { res: feature.attributes, screePoints: { x: screePoints.x + 20, y: screePoints.y + 10 } })
  })
}
// 创建要素图层
const createFeatureLayer = (layerId:any, data:any) => {
  if (map.mapView.map.findLayerById(layerId)) {
    return false
  }
  const FeatureLayer = map.ArcGisMapObj.FeatureLayer
  const features:any = []
  const layerFields:any = [{ name: 'ObjectID', alias: 'ObjectID', type: 'oid' }]
  if (data && data.length > 0) {
    data.forEach((res:any, index:any) => {
      // 将数据所有的字段信息存入featureLayer的fields中；
      if (index === 1) {
        for (const key in data[0]) {
          const field:any = {
            alias: key,
            name: key,
            type: 'blob'
          }
          layerFields.push(field)
        }
      }
      // 是否存在热力  统计字段，若不存在
      if (!res.cnt) {
        res.cnt = 1
      }
      const graphic = new map.ArcGisMapObj.Graphic({
        geometry: {
          type: 'point',
          longitude: Number(res.longitude), // 经度
          latitude: Number(res.latitude) // 纬度
        },
        attributes: res
      })
      // graphic.setAttribute('attrs', res)
      features.push(graphic)
    })
    const _featureLayer = new FeatureLayer({
      geometryType: 'point',
      source: features,
      id: layerId,
      fields: layerFields,
      outFields: ['*'],
      objectIdField: 'ObjectID'
    })
    map.mapView.map.add(_featureLayer)
    return _featureLayer
  } else {
    return null
  }
}

// 添加点状图标数据
const addFeaturLayer = (layerButtion:any, dataArr:any, layerOptions:any, config?:any) => {
  const layerId = layerButtion.elementType
  const layerName = layerButtion.elementName
  const layerIDCODE = layerButtion.elementId
  if (map.getLayer(layerId)) {
    dataArr.forEach((d:any) => {
      d.layerName = layerName
      d.layerIDCODE = layerIDCODE
    })
    updateFeatureLayer(layerId, dataArr)
    return
  }
  const pictureMakerData:any = []
  // const layerFields:any = [{ alias: 'visible', name: 'visible' }]
  // for (const key in dataArr[0]) {
  //   const field:any = {
  //     alias: key,
  //     name: key
  //   }
  //   layerFields.push(field)
  // }
  dataArr.forEach((e:any) => {
    const item = e
    item.layerName = layerName
    item.layerIDCODE = layerIDCODE
    item.longitude = Number(e.dqjd) || mapParams.map.center[0] + Math.random()
    item.latitude = Number(e.dqwd) || mapParams.map.center[1] + Math.random()
    item.visible = 1
    pictureMakerData.push(item)
  })
  // 图片标记符号的样式(必填)
  if (layerId.indexOf('jqtc') > -1) {
    layerOptions.icon = 'jqtc'
  }
  let url:string = ''
  if (config && config.pointDO && config.pointDO.icon) {
    url = config.pointDO.icon
  } else {
    url = 'mapImg/svg/' + layerOptions.icon + '.svg'
  }
  const pictureMakerSymbol = {
    type: 'picture-marker', // 固定值，无需修改
    url: url, // 图标地址
    outline: {
      color: [1, 1, 1],
      width: '5.5px'
    },
    width: '25px', // 宽
    height: '25px' // 高
  }

  // 创建图片标记符号图层 id:图层的id data:对象数组，包含点位及相关信息 symbol:图片标记符号的样式
  // const pictureMakerLayer = map.createClusterLayer(
  //   layerId,
  //   pictureMakerData,
  //   pictureMakerSymbol
  // )
  const pictureMakerLayer = createFeatureLayer(layerId, pictureMakerData)
  if (!pictureMakerLayer) {
    return
  }
  pictureMakerLayer.renderer = { type: 'simple', symbol: pictureMakerSymbol }
  pictureMakerLayer.simpleRenderer = { type: 'simple', symbol: pictureMakerSymbol }
  pictureMakerLayer.featureReduction = null
  // pictureMakerLayer.fields.push(layerFields)
  // pictureMakerLayer.latestData = dataArr

  // 配置要素弹窗字段信息
  const popupTemplate = {
    title: '{name}',
    content: [{
      type: 'fields',
      fieldInfos: [
        {
          fieldName: 'name',
          label: '名称'
        },
        {
          fieldName: 'longitude',
          label: '经度'
        }, {
          fieldName: 'latitude',
          label: '纬度'
        }
      ]
    }]
  }
  pictureMakerLayer.popupTemplate = popupTemplate
  pictureMakerLayer.popupEnabled = false
  const layerEvent = () => {
    const layerEvt = map.layerClickHandler(layerId, function (evt:any) {
      if (drawButtonStatus) {
        return
      }
      // console.log(evt[1].attributes)
      // 图标高亮效果
      map.mapView.whenLayerView(evt[1].layer).then((layerView:any) => {
        closeHighlight()
        highligh = layerView.highlight(evt[1])
      })
      // 弹窗详情弹窗
      if (!drawButtonStatus && evt[1].attributes.clusterId) {
        map.mapView.popup.dockOptions.buttonEnabled = false
        pictureMakerLayer.popupEnabled = true
      } else {
        pictureMakerLayer.popupEnabled = false
        emit('openInfoWindow', { res: evt[1].attributes, screePoints: { x: evt[0].x + 20, y: evt[0].y + 10 } })
      }
    })
    pictureMakerLayer.layerEvt = layerEvt
    pictureMakerLayer.removeLayerEvt = pictureMakerLayer.layerEvt.remove
    return layerEvt
  }
  // 初始化标绘图层
  pictureMakerLayer.initLayerEvt = layerEvent
  layerEvent()

  // 默认点位展示形式配置 showType字段 0：点位；1：热力；2：聚合；
  // if (config && config.showType) {
  //   if (config.showType === 1) {
  //     const heatConfig = JSON.parse(config.heatmapDO.config)
  //     heatmapSwitch(layerId, true, heatConfig)
  //   }
  //   if (config.showType === 2) {
  //     const heatConfig = JSON.parse(config.collectDO.content)
  //     clusterSwitch(layerId, true, heatConfig)
  //   }
  // }
  // clusterSwitch(layerId, true)
  goToFeatureLayer(layerId)
}
// 图层要素更新
const updateFeatureLayer = (layerId:any, newData:any) => {
  const layer = map.getLayer(layerId)
  let oldFeatures:any = []
  layer.queryFeatures().then((res:any) => {
    oldFeatures = res.features
    const newFeatures = arrToFeatures(newData)
    // console.log(oldFeatures)
    // console.log(newFeatures)
    // 图层需删除的要素
    const del_Features = nonExist(oldFeatures, newFeatures)

    // 图层需增加的要素
    const add_Features = nonExist(newFeatures, oldFeatures)

    // console.log(del_Features)
    // console.log(add_Features)
    // 地图执行要素更新；
    layer.applyEdits({
      addFeatures: add_Features,
      deleteFeatures: del_Features
    }).then((r:any) => {
      goToFeatureLayer(layerId)
    })
  })
  // .then((res:any) => {
  //   layer.queryFeatures()
  //   console.log(layer.source.items)
  // })
  // 数组比较去重
  const arrRes = (arr1:[any], arr2:[any]) => {
    const newArr = arr1.filter((v) =>
      arr2.every((val) => val.id !== v.id)
    )
    return newArr
  }
}

// 数组比较算法：A数组中存在，但B数组中不存在
const nonExist = (a:[any], b:[any]) => {
  const non_exist_small = (a:[any], b:[any], data:any) => {
    a.forEach(function (o) {
      let exist = false
      b.forEach(function (n) {
        if (o.attributes.id === n.attributes.id) {
          exist = true
        }
      })
      if (!exist) {
        data.push(o)
      }
    })
  }
  const non_exist_large = (a:[any], b:[any], data:any) => {
    const map = new Map()
    b.forEach(function (n) {
      map.set(n.attributes.id, n)
    })
    a.forEach(function (o) {
      const s = map.get(o.attributes.id)
      if (s === undefined) {
        data.push(o)
      }
    })
  }
  const data:any = []
  if (a.length * b.length < 32) {
    non_exist_small(a, b, data)
  } else {
    non_exist_large(a, b, data)
  }
  return data
}
const arrToFeatures = (arr:any) => {
  const features:any = []
  arr.forEach((e:any) => {
    const point = {
      type: 'point',
      longitude: Number(e.dqjd) || mapParams.map.center[0] + Math.random(),
      latitude: Number(e.dqwd) || mapParams.map.center[1] + Math.random()
    }
    const graphic = new map.ArcGisMapObj.Graphic({
      geometry: point,
      attributes: e
    })
    features.push(graphic)
  })
  return features
}
// 添加热力图
const addHeatMap = (layerId:any, dataArr:any) => {
  if (map.getLayer(layerId)) {
    clearLayer(layerId)
  }
  const heatData:any = []
  dataArr.forEach((e:any) => {
    const item = {
      longitude: e.x,
      latitude: e.y,
      cnt: e.count
    }
    heatData.push(item)
  })
  map.createHeatLayer(layerId + '_heatmap', heatData)
}

// 清除图层
const clearLayer = (layerId:any) => {
  map.removeLayer(layerId)
}

// 图层开关
const layerSwitch = (layerId:any, status:any) => {
  map.setLayerVisible(layerId, status)
}

// 热力图开关
const heatmapSwitch = (layerId:any, status:any, config?:any) => {
  if (drawButtonStatus) {
    closeDrawDialog()
    drawClick(false)
  }
  const layer = map.getLayer(layerId)
  if (!layer) {
    return
  }
  if (layer.featureReduction) {
    layer.featureReduction = null
    // clusterSwitch(layerId, false)
  }
  const defaultColor = [
    { ratio: 0, color: 'rgba(0, 0, 0, 0)' },
    { ratio: 0.6, color: 'rgb(0,255,255)' },
    { ratio: 0.85, color: 'rgb(255,255,0)' },
    { ratio: 0.95, color: 'rgb(255, 0, 0)' }
  ]
  const configColor:any = []
  if (config && config.color) {
    const colorCnt = config.color.length
    config.color.forEach((item:any, index:number) => {
      let r:number = Number(((index + 1) / colorCnt).toFixed(2))
      if (index === 0) {
        r = 0
        item = 'rgba(0, 0, 0, 0)'
      }
      if (index === colorCnt - 1) {
        r = 0.95
      }
      const itemObj = {
        ratio: r,
        color: item
      }
      configColor.push(itemObj)
    })
  }
  const color = configColor.length > 0 ? configColor : defaultColor
  const rendererT = {
    type: 'heatmap',
    colorStops: color,
    field: 'cnt',
    blurRadius: 10,
    maxPixelIntensity: 10,
    minPixelIntensity: 0
  }
  if (status) {
    layer.renderer = rendererT
  } else {
    layer.renderer = layer.simpleRenderer
  }
}

// 聚合开关
const clusterSwitch = (layerId:any, status:any, config?:any) => {
  if (drawButtonStatus) {
    closeDrawDialog()
    drawClick(false)
  }
  const layer = map.getLayer(layerId)
  if (!layer) {
    return
  }
  // 聚合效果配置
  if (layer.renderer && layer.renderer.type === 'heatmap') {
    heatmapSwitch(layerId, false)
  }
  // 聚合半径
  let clusterRadius:string = '100px'
  if (config && config.collectRange) {
    clusterRadius = config.collectRange + 'px'
  }
  // 聚合标签位置
  let labelPlacement:string = 'below-center'
  if (config && config.collectLabelPosition) {
    labelPlacement = config.collectLabelPosition
  }

  const clusterConfig:any = {
    type: 'cluster',
    clusterRadius: clusterRadius,
    popupEnabled: true,
    popupTemplate: {
      title: '聚合目录',
      content: '共有 {cluster_count} 个子项',
      fieldInfos: [
        {
          fieldName: 'cluster_count',
          format: {
            places: 0,
            digitSeparator: true
          }
        }
      ]
    },
    clusterMinSize: '25px',
    clusterMaxSize: '35px',
    labelingInfo: [
      {
        deconflictionStrategy: 'none',
        labelExpressionInfo: {
          expression: "Text($feature.cluster_count, '#,###')"
        },
        symbol: {
          type: 'text',
          color: '#ffffff',
          haloColor: [0, 0, 0, 0.85],
          haloSize: 1,
          font: {
            weight: 'bold',
            family: 'Noto Sans',
            size: '12px'
          }
        },
        maxScale: 0,
        minScale: 20000000,
        labelPlacement: labelPlacement
      }
    ]
  }
  // 设置聚合样式
  if (config && config.collectStyle) {
    if (config.collectStyle === '气泡聚合') {
      // 气泡聚合样式
      const symbol = {
        type: 'simple-marker',
        color: config.color || 'yellow',
        style: 'circle',
        outline: {
          width: 1.5,
          color: 'gray'
        }
      }
      clusterConfig.symbol = symbol
    }
  }

  if (status) {
    layer.featureReduction = clusterConfig
  } else {
    layer.featureReduction = null
  }
}

// 根据要素
const searchFeature = (searchMenu:any, content:any, ifSearchDialog:boolean = true) => {
  const result: any[] = []
  const searchFiled = ['search1', 'search2', 'search3', 'search4', 'search5', 'search6']
  const layer = map.getLayer(searchMenu.element_type)
  content = content.value || content

  searchFiled.forEach((f:any) => {
    if (searchMenu[f]) {
      layer.source.items.forEach((e:any) => {
        const a = String(e.attributes[searchMenu[f]])
        if (a && a.indexOf(String(content)) > -1) {
          const item = {
            text: a,
            feature: e
          }
          result.push(item)
        }
      })
    }
  })

  // 判断是否是搜索弹窗查询
  if (ifSearchDialog) {
    emit('getResultList', result)
  } else {
    if (result && result[0] && result[0].feature) {
      goToFeature(result[0].feature)
    }
  }
}

// 初始化标绘图层
const initDrawLyer = (data:any) => {
  const layer = map.getLayer('sketchLayer')
  const user_polygons:any = []
  const symbol = {
    type: 'simple-fill',
    color: [128, 128, 128, 0], // 填充颜色
    outline: { // 边线颜色及线条宽度
      style: 'dot',
      color: '#2eade8',
      width: 1.5
    }
  }
  data.forEach((e:any) => {
    const content = JSON.parse(e.p_content)
    if (!content || !content.rings) {
      return
    }
    const polygon = {
      type: 'polygon',
      rings: content.rings
    }

    const graphic = new map.ArcGisMapObj.Graphic({
      geometry: polygon,
      symbol: symbol,
      attributes: e
    })
    // 地图执行要素更新；
    layer.graphics.add(graphic)
  })
}
// 关闭图层过滤弹窗触发
const closeFilterDialog = () => {
  const symbol = {
    type: 'simple-fill',
    color: [128, 128, 128, 0], // 填充颜色
    outline: { // 边线颜色及线条宽度
      style: 'dot',
      color: '#2eade8',
      width: 1.5
    }
  }
  if (selectedGraphic) {
    selectedGraphic.symbol = symbol
    selectedGraphic = null
  }
}
// 存储新增绘制面
const saveGraphic = (graphic:any, geometry:any) => {
  // console.log(JSON.stringify(geometry))
  const param = {
    pcontent: JSON.stringify(geometry)
  }
  if (geometry && geometry.rings) {
    createDraw(param).then((res:any) => {
      graphic.attributes = res
    })
  }
}
// 删除绘制面
const delectGraphic = (graphicData:any, filterLayers:any) => {
  // 清楚过滤状态
  filterLayers.forEach((e:any) => {
    const layer = map.getLayer(e.element_type)
    let hasLayer = false
    if (layer) {
      hasLayer = true
    }
    if (!hasLayer) {
      return
    }
    layer.definitionExpression = null
  })
  const graphic = toRaw(graphicData) // 取消响应式，避免冲突报错
  // 地图中删除
  map.getLayer('sketchLayer').remove(graphic)
  // 数据库删除
  const param = {
    id: graphic.attributes.id
  }
  deleteDraw(param)
}
// 判断标绘面内包含的图层要素
const featureInDrawGraphic = (drawGraphicData:any, layerId:any, layerStauts:any) => {
  // 定义geometryEngine
  const drawGraphic = toRaw(drawGraphicData)
  const layer = map.getLayer(layerId)
  let hasLayer = false
  if (layer) {
    hasLayer = true
  }
  if (!hasLayer) {
    return
  }
  if (layerStauts) {
    layer.definitionExpression = null
    return
  }
  const geometryEngine = map.ArcGisMapObj.geometryEngine
  let darwGeometry:any = null
  if (drawGraphic.geometry.spatialReference.isWebMercator) {
    darwGeometry = map.ArcGisMapObj.webMercatorUtils.webMercatorToGeographic(drawGraphic.geometry)
  } else {
    darwGeometry = drawGraphic.geometry
  }
  // 读取当前过滤图层的全部要素
  const oldFeatures:any = []
  layer.queryFeatures().then((res:any) => {
    res.features.forEach((e:any) => {
      // e.setAttribute('filterGraphicId', drawGraphic.attributes.id)
      const isContained = geometryEngine.contains(darwGeometry, e.geometry)
      if (!layerStauts) {
        // if (e.attributes.visible === 0) {
        //   return
        // }
        e.attributes.visible = isContained ? 0 : 1
      }
    })
    layer.applyEdits({
      updateFeatures: res.features
    }).then((r:any) => {
      layer.definitionExpression = 'visible = 1'
      // layer.definitionExpression = `visible = 1 and filterGraphicId = ${drawGraphic.attributes.id}`
    })
  })
  // layer.source.items.forEach((e:any) => {
  //   const isContained = geometryEngine.contains(darwGeometry, e.geometry)
  //   console.log(isContained)
  //   e.visible = isContained
  // })
}

// 热力图显示数据过滤
const changeHeatMap = (layerId:string, startTime?:any, endTime?:any) => {
  const layer = map.getLayer(layerId)
  layer.queryFeatures().then((res:any) => {
    console.log(res.features)
  })
  layer.definitionExpression = `parseDate > ${startTime} and parseDate < ${endTime}`
}
// 子组件方法传给父组件
defineExpose({
  toggleBasemap,
  addFeaturLayer,
  addHeatMap,
  layerSwitch,
  heatmapSwitch,
  clusterSwitch,
  closeDrawDialog,
  clearLayer,
  searchFeature,
  goToFeature,
  initDrawLyer,
  delectGraphic,
  featureInDrawGraphic,
  changeHeatMap,
  closeHighlight,
  closeFilterDialog
})

</script>
<script lang="ts">
export default {
  name: 'MapApp'
}
</script>
<style lang="scss" scoped>
#mapContainer {
  width: 100%;
  height: 100%;
  margin: 0;
  padding: 0;
  .mapCtrl_right {
    position: absolute;
    transition: all 0.5s ease-out;
    bottom: 15px;
    right: 15px;
    display: grid;
    .mapBtn {
      position: relative;
      width: 30px;
      height: 30px;
      font-size: 12px;
      color: white;
      background-color: rgba(0, 0, 0, 0.635);
      border-radius: 30px;
      border: 1px solid #57585a;
      text-align: center;
      cursor: pointer;
      z-index: 999;
      margin: 2px;
    }
    .mapBtn:hover {
      border: 1px solid #0d85dc;
    }
  }
  .mapCtr_mid {
    position: absolute;
    display: flex;
    top: 35%;
    right: 5px;
    #drawTools {
      // width: 10%;
      font-size: 8px;
      position: relative;
    }
  }
  .mapCtrl_left{
    position: absolute;
    display: flex;
    bottom: 5px;
    left: 5px;
    // height: 25px;
    background-color: rgba(0, 0, 0, 0.635);
    border-radius: 5px;
    // padding: 2px;
    #scaleBar {
      position: relative;
      color: white;
      // background-color: rgba(0, 0, 0, 0.635);
      // border: 1px solid #57585a;
    }
    .mapPosition {
      font-size: 8px;
      position: relative;
      color: white;
      // background-color: rgba(0, 0, 0, 0.635);
      margin: 5px;
    }
  }
}
</style>
